package com.ltg.file.fastdfs.service;

import com.ltg.file.entity.FileInfo;
import com.ltg.file.fastdfs.conf.FastDFSProperties;
import com.ltg.file.sevice.FileService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.csource.common.MyException;
import org.csource.common.NameValuePair;
import org.csource.fastdfs.*;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.io.Serializable;
import java.util.List;
import java.util.Properties;

/**
 * <p> ClassName: FastDFSService </p>
 * <p> Package: com.ltg.file.fastdfs.service </p>
 * <p> Description: </p>
 * <p></p>
 *
 * @Author: LTG
 * @Create: 2023/5/21 - 11:30
 * @Version: v1.0
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class FastDFSService implements FileService {

    private final FastDFSProperties properties;
    private TrackerClient trackerClient;
    private String splitExtName(String filename) {
        if (!StringUtils.hasText(filename)) {
            return "";
        }
        if (!filename.contains(".")) {
            return "";
        }
        String[] split = filename.split("[.]");
        return split[split.length - 1];
    }

    private String concatUrl(String relativePath) {
        String endpoint = this.properties.getEndpoint();
        if (!StringUtils.hasText(endpoint)) {
            return relativePath;
        }
        if (StringUtils.endsWithIgnoreCase(endpoint, "/")) {
            endpoint = endpoint.substring(0, endpoint.length() - 1);
        }
        return endpoint + "/" + relativePath;
    }

    public void afterPropertiesSet() throws Exception {
        Assert.hasText(properties.getEndpoint(), "FastDFS外部访问地址[app.file.fastdfs.entpoint]不能为空");
        Assert.isTrue(!CollectionUtils.isEmpty(properties.getTracker().getServers()),
                "FastDFS Tracker 服务器[app.file.fastdfs.tracker.servers]不能为空");
        try {
            Properties prop = new Properties();
            prop.put(ClientGlobal.PROP_KEY_CONNECT_TIMEOUT_IN_SECONDS, properties.getConnectTimeout());
            prop.put(ClientGlobal.PROP_KEY_NETWORK_TIMEOUT_IN_SECONDS, properties.getNetworkTimeout());
            prop.put(ClientGlobal.PROP_KEY_CHARSET, properties.getCharset());
            prop.put(ClientGlobal.PROP_KEY_HTTP_ANTI_STEAL_TOKEN, false);
            prop.put(ClientGlobal.PROP_KEY_HTTP_SECRET_KEY, properties.getSecretKey());
            prop.put(ClientGlobal.PROP_KEY_HTTP_TRACKER_HTTP_PORT, properties.getTracker().getHttpPort());
            prop.put(ClientGlobal.PROP_KEY_TRACKER_SERVERS, String.join(",", properties.getTracker().getServers()));
            prop.put(ClientGlobal.PROP_KEY_CONNECTION_POOL_ENABLED, properties.getConnectionPool().isEnabled());
            prop.put(ClientGlobal.PROP_KEY_CONNECTION_POOL_MAX_COUNT_PER_ENTRY, properties.getConnectionPool().getMaximumPoolSize());
            prop.put(ClientGlobal.PROP_KEY_CONNECTION_POOL_MAX_IDLE_TIME, properties.getConnectionPool().getMaxIdleTime());
            prop.put(ClientGlobal.PROP_KEY_CONNECTION_POOL_MAX_WAIT_TIME_IN_MS, properties.getConnectionPool().getMaxWaitTimeInMs());
            ClientGlobal.initByProperties(prop);
            log.info("FastDFS配置信息: {}", ClientGlobal.configInfo());
            this.trackerClient = new TrackerClient(ClientGlobal.g_tracker_group);
            this.storageClient();
        } catch (IOException | MyException e) {
            log.error("FastDFS初始化配置出现错误！{}", e.getMessage());
            if (log.isDebugEnabled()) {
                e.printStackTrace();
            }
        }
    }

    private StorageClient storageClient() {
        try {
            TrackerServer trackerServer = this.trackerClient.getTrackerServer();
            StorageServer storageServer = this.trackerClient.getStoreStorage(trackerServer);
            List<String> storageServers = this.properties.getStorage().getServers();
            if (!CollectionUtils.isEmpty(storageServers)) {
                String ipAddr = storageServers.get(0);
                String ip;
                int port = this.properties.getStorage().getPort();
                if (ipAddr.contains(":")) {
                    String[] split = ipAddr.split(":");
                    ip = split[0];
                    port = Integer.parseInt(split[1]);
                } else {
                    ip = ipAddr;
                }
                if (storageServer == null) {
                    throw new IllegalArgumentException("FastDFS调用出现错误！errno: " + this.trackerClient.getErrorCode());
                }
                storageServer = new StorageServer(ip, port, storageServer.getStorePathIndex());
            }
            StorageClient client = new StorageClient(trackerServer, storageServer);
            log.info("store_index: {}", storageServer.getIndex());
            log.info("store_path: {}", storageServer.getStorePathIndex());
            log.info("socket_address: {}", storageServer.getInetSocketAddress());
            return client;
        } catch (IOException | MyException e) {
            log.error("FastDFS 创建 StorageClient 出现错误！{}", e.getMessage());
            if (log.isDebugEnabled()) {
                e.printStackTrace();
            }
            throw new IllegalArgumentException(e.getMessage());
        }
    }




    @Override
    public FileInfo upload(MultipartFile file) {
        FileInfo info = new FileInfo();
        try {
            info.setOriginName(file.getOriginalFilename());
            info.setFileSize(file.getSize());
            info.setContentType(file.getContentType());
            info.setExtensionName(splitExtName(file.getOriginalFilename()));
            log.info("fileInfo: {}", info);
            NameValuePair[] metaList = new NameValuePair[2];
            metaList[0] = new NameValuePair("file_name", info.getFileName());
            metaList[1] = new NameValuePair("file_length", String.valueOf(info.getFileSize()));
            String[] uploadFile = this.storageClient().upload_file(file.getBytes(), info.getExtensionName(), metaList);
            String relativePath = uploadFile[0] + "/" + uploadFile[1];
            info.setPath(relativePath);
            info.setUrl(concatUrl(relativePath));
        } catch (IOException | MyException e) {
            log.error("FastDFS上传文件出现错误！{}", e.getMessage());
            if (log.isDebugEnabled()) {
                e.printStackTrace();
            }
            throw new IllegalArgumentException(e.getMessage());
        }
        log.info("fileInfo: {}", info);
        return info;
    }
}
